// Modified from http://www.codeproject.com/KB/cpp/C___enums_to_strings.aspx
// Macros to convert an enum value to a string

// I felt kind of sick after writing this.

#undef DECL_ENUM_ELEMENT
#undef BEGIN_ENUM
#undef END_ENUM

#ifndef GENERATE_ENUM_STRINGS
#define DECL_ENUM_ELEMENT( element ) element
#define BEGIN_ENUM( ENUM_NAME ) \
	struct ENUM_NAME { \
	private: \
		static const char* sEnum[]; \
	public: \
		typedef std::vector<const char*> StringList; \
		typedef enum tagEnum
#define END_ENUM( ENUM_NAME ) \
		Enum; \
		static const char* getString(ENUM_NAME::Enum e); \
		static const StringList& getEnumStrings(); \
		static ENUM_NAME::Enum fromString(const String&); \
	};


#else
#define DECL_ENUM_ELEMENT( element ) #element
#define BEGIN_ENUM( ENUM_NAME ) const char* ENUM_NAME::sEnum[] = 
#define END_ENUM( ENUM_NAME ) \
		; \
	const char* ENUM_NAME::getString(ENUM_NAME::Enum e) { \
		if ( e < (sizeof(ENUM_NAME::sEnum)/sizeof(ENUM_NAME::sEnum[0])) ) \
			return ENUM_NAME::sEnum[e]; \
		else \
			return "unknown"; } \
		\
		const ENUM_NAME::StringList& ENUM_NAME::getEnumStrings() { \
			static ENUM_NAME::StringList names; \
			if (names.size()==0) \
			  for (size_t i=0 ; i<(sizeof(ENUM_NAME::sEnum)/sizeof(ENUM_NAME::sEnum[0])) ; i++) \
			    names.push_back(ENUM_NAME::sEnum[i]); \
			return names; \
		} \
		ENUM_NAME::Enum ENUM_NAME::fromString(const String& s) \
		{ \
			const ENUM_NAME::StringList& names = getEnumStrings(); \
			size_t i; \
			for (i=0 ; i<names.size() ; i++) \
			{ \
				if (names[i] == s) \
					break; \
			} \
			if (i != names.size()) \
				return static_cast<ENUM_NAME::Enum>(i); \
			else \
				return static_cast<ENUM_NAME::Enum>(-1); \
		}

#endif